package com.example.feigner;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author cxx
 * @create 2020-01-15 23:34
 **/
@Component
public class ILoadBalanceClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
    // Map Key service Name , Value URLs
    private volatile Map<String, Set<String>> targetUrlsCache = new HashMap<> ();

    @Autowired
    private DiscoveryClient discoveryClient;

    @Scheduled(fixedRate = 10 * 1000) // 10 秒钟更新一次缓存
    public void updateTargetUrlsCache() { // 更新目标 URLs
        // 获取当前应用的机器列表
        Map<String, Set<String>> newTargetUrlsCache = new HashMap<> ();
        discoveryClient.getServices().forEach(serviceName -> {
            List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName);
            Set<String> newTargetUrls = serviceInstances
                    .stream()
                    .map(s ->
                            s.isSecure() ?
                                    "https://" + s.getHost() + ":" + s.getPort() :
                                    "http://" + s.getHost() + ":" + s.getPort()
                    ).collect(Collectors.toSet());
            newTargetUrlsCache.put(serviceName, newTargetUrls);
        });

        this.targetUrlsCache = newTargetUrlsCache;
    }
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        URI uri = request.getURI ();
        String host = uri.getHost ();
        Set<String> urlSet = targetUrlsCache.get (host);
        List<String> urls = new LinkedList<> (urlSet);
        int index = new Random ().nextInt (urlSet.size ());
        String url =urls.get (index);
        url = url+uri.getPath ();
        URL requestURL = new URL (url);
        URLConnection urlConnection = requestURL.openConnection ();

        return new SimpleClientHttpResponse(urlConnection);
    }

}
